#include "Rational.h"
#include <algorithm>

Rational::Rational():p(0),q(1){}
Rational::Rational(int p):p(p),q(1){}
Rational::Rational(int p, int q):p(p),q(q){
	if (q==0) {
		q=1;
	}
	simplify();
}
Rational::Rational(const Rational& r):p(r.p),q(r.q){}

Rational& Rational::operator=(const Rational& r) {
	if (this != &r) {
		Rational tmp(r);
		swap(tmp);
	}
	return *this;
}

void Rational::swap(Rational& r) {
	std::swap(p, r.p);
	std::swap(q, r.q);
}

Rational operator+(const Rational& a, const Rational& b)  {
	Rational res = a;
	res += b;
	return res;
}

Rational operator-(const Rational& a, const Rational& b)  {
	Rational res = a;
	res -= b;
	return res;
}

Rational operator*(const Rational& a, const Rational& b)  {
	Rational res = a;
	res *= b;
	return res;
}

Rational operator/(const Rational& a, const Rational& b)  {
	Rational res = a;
	res /= b;
	return res;
}

Rational& Rational::operator+=(const Rational& r) {
	int np = p*r.q + r.p*q;
	int nq = q*r.q;
	p = np;
	q = nq;
	simplify();
	return *this;
}

Rational& Rational::operator-=(const Rational& r) {
	int np = p*r.q - r.p*q;
	int nq = q*r.q;
	p = np;
	q = nq;
	simplify();
	return *this;
}

Rational& Rational::operator*=(const Rational& r) {
	p *= r.p;
	q *= r.q;
	simplify();
	return *this;
}

Rational& Rational::operator/=(const Rational& r) {
	p *= r.q;
	q *= r.p;
	simplify();
	return *this;
}

Rational Rational::operator+() const {
	return *this;
}

Rational Rational::operator-() const {
	return Rational(-p, q);
}

bool operator==(const Rational& a, const Rational& b) {
	return (a.p*b.q == b.p*a.q);
}

bool operator!=(const Rational& a, const Rational& b) {
	return !(a == b);
}

bool operator<(const Rational& a, const Rational& b) {
	if (b.q*a.q > 0) {
		return (a.p*b.q < b.p*a.q);
	} else {
		return (a.p*b.q > b.p*a.q);
	}
}

bool operator>(const Rational& a, const Rational& b) {
	return !(a < b) && !(a == b);
}

bool operator>=(const Rational& a, const Rational& b) {
	return !(a < b);
}

bool operator<=(const Rational& a, const Rational& b) {
	return !(a > b);
}

Rational& Rational::operator++() {
	(*this)+=1;
	return *this;
}

Rational Rational::operator++(int) {
	Rational res = *this;
	(*this)+=1;
	return res;
}

Rational& Rational::operator--() {
	(*this)-=1;
	return *this;
}

Rational Rational::operator--(int) {
	Rational res = *this;
	(*this)-=1;
	return res;
}

void Rational::simplify() {
	int r = gcd(p, q);
	p /= r;
	q /= r;
}

int Rational::gcd(int a, int b) {
	if (a < 0) {
		 a = -a;
	}
	if (b < 0) {
		b = -b;
	}
	if (a == 0) {
		return b;
	} else if (b
		== 0) {
		return a;
	} else if (a == b) {
		return a;
	} else if (a > b) {
		return gcd(a % b, b);
	} else {
		return gcd(b % a, a);
	}
}
